{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Adversarial Robustness Toolbox (ART) and scikit-learn Pipeline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook contains an example of generating adversarial samples using a black-box attack against a scikit-learn pipeline consisting of principal component analysis (PCA) and a support vector machine classifier (SVC), but any other valid pipeline would work too. The pipeline is first optimised using grid search with cross validation. The adversarial samples are created with black-box `HopSkipJump` attack. The training data is MNIST, becasue of its intuitive visualisation, but any other dataset including tabular data would be suitable too."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from sklearn import datasets\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.svm import SVC\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "from art.utils import load_dataset\n",
    "from art.classifiers import SklearnClassifier\n",
    "from art.attacks import HopSkipJump\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load the training and testing dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_features = 28*28\n",
    "(x_train, y_train), (x_test, y_test), _, _ = load_dataset('mnist')\n",
    "x_train = x_train.reshape((x_train.shape[0], n_features))\n",
    "x_test = x_test.reshape((x_test.shape[0], n_features))\n",
    "y_train = np.argmax(y_train, axis=1)\n",
    "y_test = np.argmax(y_test, axis=1)\n",
    "\n",
    "# Select a smaller set of samples to accelerate notebook example, remove for higher accuracy\n",
    "x_train = x_train[0:1000]\n",
    "x_test = x_test[0:100]\n",
    "y_train = y_train[0:1000]\n",
    "y_test = y_test[0:100]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a pipeline containing PCA and SVC classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "svc = SVC(C=1.0, kernel='rbf')\n",
    "pca = PCA()\n",
    "pipeline = Pipeline(steps=[('pca', pca), ('svc', svc)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Grid search and cross validation to optimise number of PCA components and error term penalty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best parameter (CV score=0.910):\n",
      "{'pca__n_components': 20, 'svc__C': 1.0}\n"
     ]
    }
   ],
   "source": [
    "param_grid = {'pca__n_components': [5, 20, 30, 40, 50, 64],\n",
    "              'svc__C': np.logspace(-4, 4, 5)}\n",
    "search = GridSearchCV(estimator=pipeline, param_grid=param_grid, iid=False, cv=5)\n",
    "search.fit(x_train, y_train)\n",
    "print(\"Best parameter (CV score=%0.3f):\" % search.best_score_)\n",
    "print(search.best_params_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a black-box attack using ART"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "classifier = SklearnClassifier(model=search.best_estimator_)\n",
    "attack = HopSkipJump(classifier=classifier, targeted=False, norm=np.inf, max_iter=100, max_eval=100,\n",
    "                     init_eval=100, init_size=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate adversarial samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_test_adv = attack.generate(x_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluate benign accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on benign test samples 91.0%:\n"
     ]
    }
   ],
   "source": [
    "accuracy_test_benign = search.score(x_test, y_test)\n",
    "print('Accuracy on benign test samples {}%:'.format(accuracy_test_benign * 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluate adversarial accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on adversarial test samples 3.0%:\n"
     ]
    }
   ],
   "source": [
    "accuracy_test_adversarial = search.score(x_test_adv, y_test)\n",
    "print('Accuracy on adversarial test samples {}%:'.format(accuracy_test_adversarial * 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Inspect a benign test sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.matshow(x_test[0].reshape((28, 28)));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted label: 7\n"
     ]
    }
   ],
   "source": [
    "print('Predicted label:', search.predict(x_test[0:1])[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Inspect an adversarial test sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQQAAAECCAYAAAAYUakXAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAGj5JREFUeJzt3XmMnPV5B/DvM/de9vrGJ764bEhMvCEQk4Y0KiKHCmnUKCiKiJTUVAlSovJHUtQqUaWoqErIUbWpSEEhCrmkhKMRSSEOlesEE9bg2MYGjPHa2PgCX+tdz/30D49/LMHv9zd4YGbcfD+S5d155n3f37w7++zM/J73+Zm7Q0QEAFKdHoCIdA8lBBEJlBBEJFBCEJFACUFEAiUEEQk6khDM7Doze9bMnjezL3ViDIyZjZjZZjPbaGbDXTCeu83soJltmXDbVDN7xMy2N/6f0mXj+4qZ7W2cw41m9sEOjm++mT1qZlvN7Gkz+3zj9q44h2R8bT+H1u46BDNLA3gOwF8A2APgCQA3uvvWtg6EMLMRAEPu/nKnxwIAZvZnAE4A+L67X9q47V8AHHb32xtJdYq7f7GLxvcVACfc/WudGNNEZjYbwGx3f9LMBgBsAHADgE+hC84hGd/H0OZz2IlXCFcAeN7dX3D3MoAfA7i+A+M4Z7j7WgCH/+jm6wHc0/j6Hpx6AnVEwvi6hrvvc/cnG1+PAtgGYC665ByS8bVdJxLCXAAvTvh+Dzr04AkH8LCZbTCz1Z0eTIJZ7r6v8fV+ALM6OZgEt5jZpsZbio69pZnIzBYCuBzA4+jCc/hH4wPafA71oeKZXe3u7wDwAQCfa7wk7lp+6n1ft9WgfwfAEgArAOwD8PXODgcws34APwPwBXc/PjHWDefwDONr+znsRELYC2D+hO/nNW7rGu6+t/H/QQD34dTbnG5zoPHe8/R70IMdHs9ruPsBd6+5ex3Ad9Hhc2hmWZz6ZbvX3X/euLlrzuGZxteJc9iJhPAEgAvMbJGZ5QB8HMCDHRjHGZlZX+ODHZhZH4BrAWzhW3XEgwBuanx9E4AHOjiW1zn9i9bwEXTwHJqZAbgLwDZ3v2NCqCvOYdL4OnEO2z7LAACN6ZNvAkgDuNvdv9r2QSQws8U49aoAADIAftjp8ZnZjwBcA2A6gAMAvgzgfgA/BbAAwC4AH3P3jnywlzC+a3Dqpa4DGAFw84T36+0e39UA/hfAZgD1xs234dT79I6fQzK+G9Hmc9iRhCAi3UkfKopIoIQgIoESgogESggiEighiEjQ0YTQxWXBADS+VnXz+Lp5bEDnxtfpVwhd/UOBxteqbh5fN48N6ND4Op0QRKSLtFSYZGbXAfgWTlUc/qe7387un8v0eiE/GL6vVMeRzfS+ur9yhR7Pq7XYgPj2/T00nhovveb7sp9Ezl7dxmv8+NZT4OOr12nYs+nI9q/9Wb3u/MV+lNUqj6f43wdPv7F4pTKGbLbv1d2X+fmr9fDHnx7jz49aX5Zvf+LVn2+5XkQu9dqfl9f4z8di5yfy/PCBXhpPlV/9+ZRrJ5FLv/b5Ws9l+PhGxxNjRYyh7CX+C4JTpblnpdHo5N8wodGJmT3IGp0U8oO4cvnNiftM7XyJHrP2Cq8qtWyOxivvuozG8xue58c/eozGUxdeTON2skzj1ZmT+P5L/BfaKvwJmToQqcrt5QmzNrmPxitTeELM7zlK4yeWTaPxgWF+DdzoEL+Kvn/dDhqvj56g8VQk4ceeH9UrVtJ4/sUjNF5awK9+zqzZkBh73NfQbU9r5S2DGp2I/D/TSkI4FxqdiMgb8JZ/qGhmq81s2MyGK9Xk9zgi0nmtJISmGp24+53uPuTuQxM/ABOR7tNKQujqRici8sad9SyDu1fN7BYA/41XG508zbYxB6yc/El5feHsxBgA1C9ZQOPpk3xaqp7l+c+m8k9xbck8Hn+Bz5L4XN7DszzIp816dhX59jP5LEC6P0/jqeFtPH6Yf8qe3crHd+K6t/PtR/ksSf0In6VIF+fQ+PgVi2m876kXabw2dzqNVycvpXE2CwAANo9/BJc7NMa3n5L8/LVjkSnthrNOCADg7g8BeKiVfYhI91CloogESggiEighiEighCAigRKCiARKCCIStDTt+IbV6kgdP/vy5XQpcrXgvv00nl+5nMYrswdpvFaIXJ677Hwaz+7ga2zkJvN5/tSR4zSer/CrIUtzJ9N4di6vAynP4ecne+Qkjff/ll9tGKsT8Mjl26kKv3y5sOMQjVcWn8f3H6nTyEeuhqyuWsHjkatVY5fHZ/tIJfBoc3/79QpBRAIlBBEJlBBEJFBCEJFACUFEAiUEEQmUEEQkaGsdgpfLqI7sToxXrh2i2+de4fPcqWN8nj7WpTyz+QUaz06fSuP1Xj4PPXY57+fQ+wLvuuuDA/z4z4/QeCFSx1GfFGkTvm4jjVfecznf/3kLabx3+ys0XiuVaDxd5PP4xSUzaDx7jO9//AO8n0P/s/znF6tjqA9dQuPZ3S/z7aeTOpOXm+uHoFcIIhIoIYhIoIQgIoESgogESggiEighiEighCAiQXv7IfT3wFckXxOeX7uFbp6awq/HL17J53Fjq+vWl8yn8fSRURovz+LrIuSP8Hnu0rxIv4J1/PxYms81+4lIX/9j/PGlB/n4MjsP0nhtVqTfxHZeB2J5vq5E+nm+LgaW8H4PxRl89evs8ci6ES8k19gAQPUq3o8jE1nuPqZeSP519lR0JXgAeoUgIhMoIYhIoIQgIoESgogESggiEighiEighCAiQVvrEKxaR+Zw8lx4deXFfAfHijSc+c0Gvv2smTScHuf7ryzk2+d3Habx+gDvN5B96lkax7KlNOxbttP42NVL+P5bVDjA6yzqkXUtcjN4v4ITqxbReP9W3k+hPDlH4/U8n6vPReoQin/+NhrvfYLXWZTevpDGU8cidRhHktc8sRpfs+K0lhKCmY0AGAVQA1B1d97hRES62pvxCuF97s5buYjIOUGfIYhI0GpCcAAPm9kGM1v9ZgxIRDqn1bcMV7v7XjObCeARM3vG3ddOvEMjUawGgEJ2UouHE5G3UkuvENx9b+P/gwDuA3DFGe5zp7sPuftQLs0/ZReRzjrrhGBmfWY2cPprANcC4NfnikhXa+UtwywA95nZ6f380N1/Rbcwg5Nr9mN9573A55F9VXKvBQCwHftovP4KryNIR+KxdR/S5/E6Bu/lr6BKU/i6D7lLFtN4dpTPo1cGmuvdn6Q4i8+T97zE19UoXcbXrYgpzef9FmJ1BrHzE1N4mdexwPjf3/wm3k+hfv4svvsKGb811w/hrBOCu78AgK9cISLnFE07ikighCAigRKCiARKCCISKCGISKCEICJBe9dlcIfVk6/L9nyWb5/lw83u4dfDez+f57cK74u/83O8X8Oi943Q+I6182jcLz5B4wMP8zqM8uW8DmBwR5XGC4fKNF6L9DPI7+fjx979NJzp4+taFGqROoE8Pz+Vy/m6DDHFGXz/qRKvRCnUeR1KeRpfFyL3Cq/jSB0j62402Q9BrxBEJFBCEJFACUFEAiUEEQmUEEQkUEIQkUAJQUSC9tYhmMFzZA373ki/g2HefyUzdw4/fpGvG1Bawfv+D151gMY/NGszje/+y5dofFH+EI3/1bufo/EpKd4vYVukzuKjv/tbGnfwOoDaGG+RZ9l+vv9K5O9ThV/Tb718fLe/+yc0/s/f/gSND+zhdRy54/z81vr58zv78DCNn/zw6xqSvUZfkYwv1Vw/BL1CEJFACUFEAiUEEQmUEEQkUEIQkUAJQUQCJQQRCdpah+DFEnzbjsR4auF8voML+LoDfoj3Q6gdPUbjhV5+PXphNZ/n/snKD9B4Pc3ngh9azPsNrL1hG41fMbiTxq/v53Ucg5PGafySabyfQcykDK8DSRm/Zv/po7yfwdy+ozR+qMrrJGZ/dITGy/90Ho3H1DP872828vzu3xBZt+EIefwl3uviNL1CEJFACUFEAiUEEQmUEEQkUEIQkUAJQUQCJQQRCdpah2D5HFKLFyTHjxyn21cXzqLx+pzJNJ5ev5Xvf+cuGk8VeL+B3l/yfgbpOXweO39kOo3v2X4BjW+fwteN+PaK62j84v/gdRyH9vB1B1KD/Pwf3MfrGCwX6RdQ4/0ojj88SOPL83tp/FvrP0zjS5/iz5/xqy6k8b6NL9I4CnxdDY/087D5pB/IrsiaJw3RVwhmdreZHTSzLRNum2pmj5jZ9sb/U5o6moh0tWbeMnwPwB//afkSgDXufgGANY3vReQcF00I7r4WwOE/uvl6APc0vr4HwA1v8rhEpAPO9kPFWe6+r/H1fgD8zb2InBNanmVwdweQ+GmTma02s2EzGy7X+MUzItJZZ5sQDpjZbABo/H8w6Y7ufqe7D7n7UC7NV18Wkc4624TwIICbGl/fBOCBN2c4ItJJ0ToEM/sRgGsATDezPQC+DOB2AD81s08D2AXgY00drVSG70yei7VpU+nmJ8/jdQD9//MsjbvF+vrzVzD1cf6Wp/SBd9J4z95RGk+XeL8F8M3Ru4ePr+cIf3x2MjLP3ce3rx3kdRhe5esapM/jH0Vt/Ye5NL4qy9et+Mz6m2h8yd8/RuOYNZPHI2pzeZ1J6nlep+ALeD8Ie5HUaVQjz62GaEJw9xsTQu9v6ggics5Q6bKIBEoIIhIoIYhIoIQgIoESgogESggiErR3XYa+Amorkq/ZtyN8Hj1V4tfjx9ZdsDy/3jw9mfft92W8b37hIB//2GK+/1ZVBlqrBPUsfzqcWMH7OWRH50UOwMNHFvB+CL+47g4a/9r+a2n8wq+O0Xhspr4+bwaN53/5BN/B0KU8nuHnP3WYF6KMvje5X0btUf7cD8do6l4i8idBCUFEAiUEEQmUEEQkUEIQkUAJQUQCJQQRCdpbh5AylCcl94dPDfN1EfrG+fXyxfevpPHc+mf49sv49faFnXzdguKiaTTeqsKhMj/+DD6PH1Na0Fo3favzQoPyZP50W/gZ3s+gYLxSYKzKH39tK99/OrKuRH3L8zQe64dR+M0mvn8aBdL9fTTe80ByHUSq3lz7Qr1CEJFACUFEAiUEEQmUEEQkUEIQkUAJQUQCJQQRCdpah5AaK6L3t8lrJ9SXLaXb1zbzdRcyMyPzyGOR6+FzPD/WpvB54MpAmsZb1WqdQXaUz+PHxh/bPlZnsO8qvv8fLODr/TwwupzGj13N60TeaukyryRIz+H9JKo7eR1OcQnvx1C7JLlOx9f9jm57ml4hiEighCAigRKCiARKCCISKCGISKCEICKBEoKIBG2tQ0AuB1+U3HOgeB5fV6CQTl7TAQAyuw/SeJVGgZ6XTtC47d5P49lBvm5Dusjn8WsFPk8fqxPo3XuSxsfn9tD4W12ncNlVO2m8Flm34V83XUPjSwdH+A5aFamTye/h64LUJ/M6lvSyC2k8+vx9MXndhlQl1m2hcb/YHczsbjM7aGZbJtz2FTPba2YbG/8+2NTRRKSrNfOW4XsArjvD7d9w9xWNfw+9ucMSkU6IJgR3XwvgcBvGIiId1sqHireY2abGW4rWmvGJSFc424TwHQBLAKwAsA/A15PuaGarzWzYzIbL1eYaPYpIZ5xVQnD3A+5ec/c6gO8CuILc9053H3L3oVymtdWJReStdVYJwcxmT/j2IwC2JN1XRM4d0ToEM/sRgGsATDezPQC+DOAaM1sBwAGMALi5mYO5AZ5JzkG9wyN8B4MDNFxcPo/Gc6OROoNihR/f+VxuqtrcXG+S2Dx/qsQn6mN1BtHj90fqHH7xJI3b8gto/PuL/ysyAv50XHTjH2icV0EAvmoFj6eMxtOPbabx2E8/NcCfv5gzk28feX7VtySvO+Je5MduiCYEd7/xDDff1dTeReScotJlEQmUEEQkUEIQkUAJQUQCJQQRCZQQRCRoaz8Eq9aRfiX5mu3RVYvo9gNP7aPx/EvH+QDOT+7FAADj5/N1HQoDBRqv9PLT2bM3+bEDQLbFfggDG3m/htr0STSOzdtp2DL88b10Db+kpT/Fz9+9o9NovPr+lTSePVaicSvxjgKp47yfhEcevy3gzy8r8zqXWoHvP71+K41XyPnxxx+j256mVwgiEighiEighCAigRKCiARKCCISKCGISKCEICJBe9dlqNXgR5N71/fcv5tuHutLb0OX0njqRb5uQ3o2v149NcqvKe8p8hFWpvOOUfUMvx4/prhkBo1n1myg8fQUXkdgk/n5+cMX/53G91R5P4qv/uCzND6vyFvwpY6O0bhV+M9nbNl5fPvFU/nxI2sf5PdH+nE8vYPGI8tWIL/h+cRYapzXaIT7NXUvEfmToIQgIoESgogESggiEighiEighCAigRKCiATtrUPIZoDZyb3nS1ddSDfveZT3xR+bx+f5+4p8HjmmPqm1dQ+qPbyfQUzuGJ9Hz4yWaTw2j229/PHt+WYfjf94lNcx7K8upPFFP9hL45U5kTqJSJ3ByYtm0Xi6HKkjIPP8AFBfOp/Gq4P8/Gb6+fmtXcT3n95L1mQea+65p1cIIhIoIYhIoIQgIoESgogESggiEighiEighCAiQdv7IdjR5LUJ+jbz690rKy+m8d69vK9+ihwbAArjvN+B57M0fuIiPk/eu4c/vnqOzxXX8zxuW/g8eXrhAhp/9qt8XYRPLPo9jf/7yDU0fuI+3m9gymJeRxFbl6I4YzaNx2RHazRufbxOIHWM/3zTVb7/6suv0Hjx6iV8/6OkDmd/c3/7o/cys/lm9qiZbTWzp83s843bp5rZI2a2vfE//20Qka7XTNqoArjV3ZcBuBLA58xsGYAvAVjj7hcAWNP4XkTOYdGE4O773P3JxtejALYBmAvgegD3NO52D4Ab3qpBikh7vKEPFc1sIYDLATwOYJa7n15scT8AXiguIl2v6YRgZv0AfgbgC+7+mlVV3d2RcO2Mma02s2EzGy7X+Yd+ItJZTSUEM8viVDK4191/3rj5gJnNbsRnAzhjS2N3v9Pdh9x9KJdq7WpBEXlrNTPLYADuArDN3e+YEHoQwE2Nr28C8MCbPzwRaadm6hBWAfgkgM1mtrFx220AbgfwUzP7NIBdAD4W25Hnsqien9wPwYa30u1TMwb5ATKR/Jbh89h+JHnNCAA48d4L+P4jqv05Gs+u54/fh3gdBi5ezI+/ke//48t30vi1A7wfxb2/fg+Nz9vN+xWki3yePlaHEBOrM6jl+POnPm0SPwBvp4Da9mf4HSL6t/I6hfElyf0+6jub+3QgmhDcfR2ApBVE3t/UUUTknKDSZREJlBBEJFBCEJFACUFEAiUEEQmUEEQkaG8/hLGTwPpNyfF8nm6e3vcyjXsx0s9g1gwaH7ua1xn0vMRLr9O7DtB47cAZizlf9TZeZ5B9eheN+wLebwBr5tHwJwZ/SuMfeuDvaHzuusjKD5FwcQav00iV+Q7quaTZ8VOy67bQeO6iRTReGyjw/e86RON2CX9+sV4hAFDv5b8ffc8kP79SRV4DEu7X1L1E5E+CEoKIBEoIIhIoIYhIoIQgIoESgogESggiErS1DsEHelG9YmViPPe7p/kOCnwe1o/yfga16f189wd4nUFpGp+HTg/Mp/HciTEatyq/oN76+boAz9zKO1L99dRtNP6z4++g8cnP8r8f5nyuu57ndQIxuWMVGo/VAfj8OTz+3Ajf/3S+bkXtEK+TGR96O4333L+dxlMz+UoHxcXTE2P1Q839qusVgogESggiEighiEighCAigRKCiARKCCISKCGISNDWOoTUeAn5p15IvsP5/Hp9f/kwjZdXLT+bYQXZEp9HLxwcp3HfwOso6haZh9/6HA2XPvhOGr/uEr5uwj/OWE/jw6VeGv/1Tr7uQqzOoHCoTONW4esmpJ/bTeNjV13Ij//IUzQ+/mFehxEbf6bA+zn0reF1ID50KY1jK/ndAZDuT3785pFmFA16hSAigRKCiARKCCISKCGISKCEICKBEoKIBEoIIhJE6xDMbD6A7wOYhVOd9e9092+Z2VcA/A2A0xeh3+buD7F91fvyGL9yaWK8d3iEjqW2ZG5suFSqxOe5K5N5v4XMKJ+H9qv49e6ZbSM0DuP5uTg1TeOpyMIHn33xWhp/fPdCGl/6LO83MHYRX/ciu5v3CxhdyfsV9G0q0XisTqT+Lj7P33P/72k8hj+7AIvUGVQm8edf6h28ziJzPHldEqs1V4fQTGFSFcCt7v6kmQ0A2GBmjzRi33D3rzV1JBHpetGE4O77AOxrfD1qZtsAtPanWkS60hv6DMHMFgK4HMDjjZtuMbNNZna3mfH+TiLS9ZpOCGbWD+BnAL7g7scBfAfAEgArcOoVxNcTtlttZsNmNlwp856CItJZTSUEM8viVDK4191/DgDufsDda+5eB/BdAFecaVt3v9Pdh9x9KJvjTUJFpLOiCcHMDMBdALa5+x0Tbp894W4fAcCX1hWRrtfMLMMqAJ8EsNnMNjZuuw3AjWa2AqemIkcA3PyWjFBE2qaZWYZ1AM50oTutOTgTqzuyo6S3/tTJdPuTc/i6A/1bX6Hx+kBkXYUn+PXq6SmDNF7df4DGa5F+COnJk2i8cJjPdPdl+Dz9wzsuovEln+L9GHzebBrvfYxvj0H+8+0bOUHjqcj29WdGaLx25cU0nruUx+v9vN8B1m+i4fTLx2k8dYz/Ota2834INok8f8q8hiaMoal7icifBCUEEQmUEEQkUEIQkUAJQUQCJQQRCZQQRCRo67oMboZ6PvmafivxudJYX3zPZWncIn396yU+j++1Oo2nl/N5fjvJ9z962Uwa79vF5+mHb11J40v38Xnw8fddRuO9T/B5cGT406k8fxqNl6bynx8W9tNw3694HUDuMV5nYvlIP4wpvA6iEumHMT6Z1zEU1vJ1PWLqFy5IjPnTkRqKBr1CEJFACUFEAiUEEQmUEEQkUEIQkUAJQUQCJQQRCcybXDf+TTmY2SEAuybcNB0Ab9bfWRpfa7p5fN08NuDNH9/57s4XzkCbE8LrDm427O5DHRtAhMbXmm4eXzePDejc+PSWQUQCJQQRCTqdEO7s8PFjNL7WdPP4unlsQIfG19HPEESku3T6FYKIdBElBBEJlBBEJFBCEJFACUFEgv8D7JantSWtmMwAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.matshow(x_test_adv[0].reshape((28, 28)));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted label: 9\n"
     ]
    }
   ],
   "source": [
    "print('Predicted label:', search.predict(x_test_adv[0:1])[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L_Infinity-norm: 0.24902647710313985\n"
     ]
    }
   ],
   "source": [
    "print('L_Infinity-norm:', np.linalg.norm(x_test_adv[0] - x_test[0], ord=np.inf))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "venv36",
   "language": "python",
   "name": "venv36"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
